#include <conio.h>
#include <Windows.h>
#include <graphics.h>

//控制键 上、下、左、右 控制方向，'q' 退出
#define KEY_UP		'w'
#define KEY_LEFT	'a'
#define KEY_RIGHT	'd'
#define KEY_DOWN	's'
#define KEY_QUIT	'q'

#define RATIO	50

#define HEIGHT	800
#define WIDTH	650

#define LINE	9
#define COLUMN	12

#define isValid(pos)		pos.x >= 0 && pos.x < LINE && pos.y >= 0 && pos.y < COLUMN

#define START_X		100
#define START_Y		150

typedef		enum _PROPS		PROPS;
typedef		enum _DIRECTION DIRECTION;
typedef		struct _POSITION	POS;
typedef		int				int32;

enum _PROPS
{
	WALL,     /* 墙 */
	FLOOR,    /* 地板 */
	BOX_DES,  /* 箱子的目的地 */
	MAN,      /* 人 */
	BOX,      /* 箱子 */
	HIT,      /* 箱子命中目标 */
	ALL
};

enum _DIRECTION
{
	UP,
	DOWN,
	LEFT,
	RIGHT
};

struct _POSITION
{
	int x = 0; /* 小人所在的二维数组的行 */
	int y = 0; /* 小人所在的二维数组的列 */
};

IMAGE images[ALL];

struct _POSITION  man;

//游戏地图
int map[LINE][COLUMN] = {
{ WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL},
{ WALL, FLOOR, WALL, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, WALL, WALL},
{ WALL, FLOOR, BOX, FLOOR, WALL, BOX_DES, FLOOR, WALL, BOX_DES, FLOOR, WALL, WALL},
{ WALL, FLOOR, WALL, FLOOR, WALL, FLOOR, WALL, WALL, FLOOR, FLOOR, FLOOR, WALL},
{ WALL, FLOOR, WALL, BOX_DES, WALL, FLOOR, FLOOR, BOX, FLOOR, FLOOR, FLOOR, WALL},
{ WALL, FLOOR, FLOOR, FLOOR, WALL, MAN, FLOOR, FLOOR, FLOOR, BOX, FLOOR, WALL},
{ WALL, FLOOR, BOX_DES, FLOOR, FLOOR, BOX, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, WALL},
{ WALL, FLOOR, WALL, WALL, FLOOR, WALL, FLOOR, FLOOR, WALL, WALL, FLOOR, WALL},
{ WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL} };

bool isGameOver()
{
	for (int i = 0;i < LINE;i++)
	{
		for (int j = 0;j < COLUMN;j++)
		{
			if (map[i][j] == BOX_DES)
			{
				return false;
			}
		}
	}
	return true;
}

void gameOverScene(IMAGE* bg)
{
	putimage(0, 0, bg);
	settextcolor(WHITE);
	RECT rec = { 0, 0, WIDTH, HEIGHT };
	settextstyle(20, 0, _T("宋体"));
	drawtext(_T("恭喜您~ \n通关了"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}

void changeMap(POS* pos, PROPS prop)
{
	map[pos->x][pos->y] = prop;
	putimage(START_X + pos->y * RATIO, START_Y + pos->x * RATIO, &images[prop]);
	return;
}

void gameControl(DIRECTION direct)
{
	POS next_pos = man; // x y
	POS next_next_pos = man; // x y

	switch (direct)
	{
	case UP:
		next_pos.x--;
		next_next_pos.x -= 2;
		break;
	case DOWN:
		next_pos.x++;
		next_next_pos.x += 2;
		break;
	case LEFT:
		next_pos.y--;
		next_next_pos.y -= 2;
		break;
	case RIGHT:
		next_pos.y++;
		next_next_pos.y += 2;
		break;
	}

	if (isValid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR)
	{
		changeMap(&next_pos, MAN); // 小人前进一格
		changeMap(&man, FLOOR);
		man = next_pos;
	}
	else if (isValid(next_next_pos) && map[next_pos.x][next_pos.y] == BOX)
	{
		if (map[next_next_pos.x][next_next_pos.y] == FLOOR)
		{
			changeMap(&next_next_pos, BOX);
			changeMap(&next_pos, MAN);
			changeMap(&man, FLOOR);
			man = next_pos;
		}
		else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES)
		{
			changeMap(&next_next_pos, HIT);
			changeMap(&next_pos, MAN);
			changeMap(&man, FLOOR);
			man = next_pos;
		}
	}
}

int main(void)
{
	IMAGE ba_img;
	initgraph(HEIGHT, WIDTH);
	//加载设置图像资源
	loadimage(&ba_img, _T("background.bmp"), HEIGHT, WIDTH, true);
	//绘制到屏幕
	putimage(0, 0, &ba_img);

	//加载显示道具
	loadimage(&images[WALL], _T("wall_right.bmp"), RATIO, RATIO, true);
	loadimage(&images[FLOOR], _T("floor.bmp"), RATIO, RATIO, true);
	loadimage(&images[BOX_DES], _T("des.bmp"), RATIO, RATIO, true);
	loadimage(&images[MAN], _T("man.bmp"), RATIO, RATIO, true);
	loadimage(&images[BOX], _T("box.bmp"), RATIO, RATIO, true);
	loadimage(&images[HIT], _T("box.bmp"), RATIO, RATIO, true);

	for (int i = 0; i < LINE; i++)
	{
		for (int j = 0; j < COLUMN; j++)
		{
			if (map[i][j] == MAN)
			{
				man.x = i;
				man.y = j;
			}
			putimage(START_X + j * RATIO, START_Y + i * RATIO, &images[map[i][j]]);
		}
	}

	bool quit = false;
	do {
		if (_kbhit()) //玩家按键
		{
			char c = _getch();
			switch (c)
			{
			case KEY_UP:
				gameControl(UP);
				break;
			case KEY_LEFT:
				gameControl(LEFT);
				break;
			case KEY_RIGHT:
				gameControl(RIGHT);
				break;
			case KEY_DOWN:
				gameControl(DOWN);
				break;
			case KEY_QUIT:
				quit = true;
				break;
			}
			if (isGameOver())
			{
				gameOverScene(&ba_img);
				quit = true;
			}
		}
		Sleep(100);
	} while (quit == false);

	//游戏结束，释放资源
	closegraph();

	system("pause");
	return 0;
}